﻿using System;
using System.Windows.Forms;
using System.IO;
using RSPJ.Struct;
using RSPJ.Windows;
using System.Collections.Generic;

namespace RSPJ.Function
{
    public class funcRW
    {
        public void open_imagefile()
        {
            using (OpenFileDialog ofd = new OpenFileDialog())              // 实例化一个 OpenFileDialog 的对象
            {
                ofd.Multiselect = true;                                 // 允许多选
                if (ofd.ShowDialog() == DialogResult.OK)                // 显示打开本地文件的窗体
                {
                    string[] filePaths = ofd.FileNames;                 // 把完整路径名称赋给filePaths
                    string[] fileNames = ofd.SafeFileNames;             // 把文件名称赋给fileNames
                    for (int i = 0; i < filePaths.Length; i++)
                    {
                        // 判断文件是否已经打开
                        int flag = 0;
                        for (int j = 0; j < GlobalData.fileList.Count; j++)
                        {
                            if (filePaths[i] == GlobalData.fileList[j].Path)
                            {
                                flag = 1;
                                continue;
                            }
                        }

                        // 文件未打开则打开文件，已打开则跳过
                        if (flag == 1)
                            continue;
                        else
                        {
                            // 读取文件
                            Files file = new Files();
                            file.Name = fileNames[i];
                            for (int j = 0; j < GlobalData.fileList.Count; j++)
                            {
                                if (file.Name == GlobalData.fileList[j].Name)
                                {
                                    int tmp = 1, k = 0;
                                    do
                                    {
                                        file.Name = fileNames[i] + "(" + tmp + ")";
                                        for (k = 0; k < GlobalData.fileList.Count; k++)
                                        {
                                            if (file.Name == GlobalData.fileList[k].Name)
                                            {
                                                tmp++;
                                                break;
                                            }
                                        }
                                    } while (k != GlobalData.fileList.Count);
                                }
                            }
                            file.Path = filePaths[i];

                            // 读取头文件
                            string metaPath = file.Path + ".hdr";
                            if (File.Exists(metaPath))
                            {
                                read_metadata(metaPath, ref file.Head);
                            }
                            else
                            {
                                using (EditHeader eh = new EditHeader(file.Head))
                                {
                                    if (eh.ShowDialog() == DialogResult.OK)
                                    {
                                        file.Head = eh.head;
                                    }
                                    else
                                    {
                                        MessageBox.Show("文件" + fileNames[i] + "因没有头文件信息无法打开", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                        continue;
                                    }
                                }
                            }

                            // 读取图像文件
                            try
                            {
                                read_data(filePaths[i], ref file.IntArray, file.Head);
                            }
                            catch (IOException e)
                            {
                                MessageBox.Show("读取文件失败！\n错误信息：" + e.ToString(), "错误信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                continue;
                            }

                            // 存入文件列表
                            GlobalData.fileList.Add(file);

                            // 打开波段列表
                            if (WindowsStatus.availableBandsList == false)
                            {
                                AvailableBandsList bandsWindow = new AvailableBandsList();
                                WindowsStatus.availableBandsList = true;
                                bandsWindow.Show();
                            }
                        }
                    }
                }
            }
        }

        public void mergedata(List<Files> list, out Files file)
        {
            int bands = 0;
            foreach (Files item in list)
            {
                bands += item.Head.Bands;
            }
            file = new Files();
            file.Head = list[0].Head.Clone();
            file.Head.Bands = bands;
            file.Head.Interleave = "bsq";

            file.Name = "MergedFiles";
            file.IntArray = new double[bands, file.Head.Lines, file.Head.Samples];

            int p = 0;
            foreach (Files item in list)
            {
                for (int i = 0; i < item.Head.Bands; i++)
                {
                    for (int j = 0; j < file.Head.Lines; j++)
                    {
                        for (int k = 0; k < file.Head.Samples; k++)
                        {
                            file.IntArray[p, j, k] = item.IntArray[i, j, k];
                        }
                    }
                    p++;
                }
            }
        }

        private void read_metadata(string filePath, ref Head head)
        {
            string s = filePath;
            try
            {
                StreamReader sr = new StreamReader(s);
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    string[] a = line.Split('=');
                    if (a[0].Trim() == "samples")
                    {
                        head.Samples = Int32.Parse(a[1].Trim());
                    }

                    if (a[0].Trim() == "lines")
                    {
                        head.Lines = Int32.Parse(a[1].Trim());
                    }

                    if (a[0].Trim() == "bands")
                    {
                        head.Bands = Int32.Parse(a[1].Trim());
                    }

                    if (a[0].Trim() == "header offset")
                        head.Header_offset = Int32.Parse(a[1].Trim());

                    if (a[0].Trim() == "file type")
                        head.File_type = a[1].Trim();

                    if (a[0].Trim() == "data type")
                        head.Data_type = Int32.Parse(a[1].Trim());

                    if (a[0].Trim() == "interleave")
                        head.Interleave = a[1].Trim();
                }
                sr.Close();
            }
            catch
            {
                MessageBox.Show("读取头文件失败!", "错误信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void read_data(string dataPath, ref double[,,] intArray, Head head)
        {
            FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            intArray = new double[head.Bands, head.Lines, head.Samples];
            if (head.Interleave == "bsq")
            {
                for (int i = 0; i < head.Bands; i++)
                {
                    for (int j = 0; j < head.Lines; j++)
                    {
                        for (int k = 0; k < head.Samples; k++)
                        {
                            byte b = br.ReadByte();
                            intArray[i, j, k] = Convert.ToDouble(b);
                        }
                    }
                }
            }
            if (head.Interleave == "bil")
            {
                for (int j = 0; j < head.Lines; j++)
                {
                    for (int i = 0; i < head.Bands; i++)
                    {
                        for (int k = 0; k < head.Samples; k++)
                        {
                            byte b = br.ReadByte();
                            intArray[i, j, k] = Convert.ToDouble(b);
                        }
                    }
                }
            }
            if (head.Interleave == "bip")
            {
                for (int j = 0; j < head.Lines; j++)
                {
                    for (int k = 0; k < head.Samples; k++)
                    {
                        for (int i = 0; i < head.Bands; i++)
                        {
                            byte b = br.ReadByte();
                            intArray[i, j, k] = Convert.ToDouble(b);
                        }
                    }
                }
            }
            br.Close();
        }

        public void write_imagefile(Files file, string P)
        {
            string metadata = P + ".hdr";
            write_metadata(metadata, file.Head);
            switch (file.Head.Interleave)
            {
                case "bsq":
                    ToBSQ(P, file);
                    break;
                case "bil":
                    ToBIL(P, file);
                    break;
                case "bip":
                    ToBIP(P, file);
                    break;
                default:
                    break;
            }
        }

        public void write_metadata(string P, Head head)
        {
            StreamWriter sw = new StreamWriter(P);
            sw.WriteLine("ENVI");
            sw.WriteLine("samples = " + head.Samples);
            sw.WriteLine("lines = " + head.Lines);
            sw.WriteLine("bands = " + head.Bands);
            sw.WriteLine("header offset = " + head.Header_offset);
            sw.WriteLine("file type = " + head.File_type);
            sw.WriteLine("data type = " + head.Data_type);
            sw.WriteLine("interleave = " + head.Interleave);
            sw.Close();
        }

        private void ToBSQ(string P, Files file)
        {
            BinaryWriter bw = new BinaryWriter(File.Open(P, FileMode.Create));
            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Lines; j++)
                {
                    for (int k = 0; k < file.Head.Samples; k++)
                    {
                        if (file.Head.Data_type == 1)
                            bw.Write(Convert.ToByte(file.IntArray[i, j, k]));
                        if (file.Head.Data_type == 5)
                            bw.Write(file.IntArray[i, j, k]);
                    }
                }
            }
            bw.Close();
        }

        private void ToBIL(string P, Files file)
        {
            BinaryWriter bw = new BinaryWriter(File.Open(P, FileMode.Create));
            for (int j = 0; j < file.Head.Lines; j++)
            {
                for (int i = 0; i < file.Head.Bands; i++)
                {
                    for (int k = 0; k < file.Head.Samples; k++)
                    {
                        if (file.Head.Data_type == 1)
                            bw.Write(Convert.ToByte(file.IntArray[i, j, k]));
                        if (file.Head.Data_type == 5)
                            bw.Write(file.IntArray[i, j, k]);
                    }
                }
            }
            bw.Close();
        }

        private void ToBIP(string P, Files file)
        {
            BinaryWriter bw = new BinaryWriter(File.Open(P, FileMode.Create));
            for (int j = 0; j < file.Head.Lines; j++)
            {
                for (int k = 0; k < file.Head.Samples; k++)
                {
                    for (int i = 0; i < file.Head.Bands; i++)
                    {
                        if (file.Head.Data_type == 1)
                            bw.Write(Convert.ToByte(file.IntArray[i, j, k]));
                        if (file.Head.Data_type == 5)
                            bw.Write(file.IntArray[i, j, k]);
                    }
                }
            }
            bw.Close();
        }
    }
}
